﻿using Core.DeviceProtocol;
using Core.Msg;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Core.ChannelProtocol;
using Core.Modbus;
using Core.Model;


namespace ModbusTcp
{

    public class ModbusTcp : BaseDevProtocol
    {
        #region 属性字段
        protected List<ModbusRxTxCommand> _mSendFrame = new List<ModbusRxTxCommand>();
        protected int _sendIndex = -1;
        protected ModbusRxTxCommand _modItem;
        private UInt16 _packageIndex = 1;
        #endregion

        #region 初始化协议信息

        public override bool Initialize(BaseChannel channel, Device dev, List<Operation> operations, List<DataItem> dataItems)
        {
             base.Initialize(channel, dev, operations, dataItems);
            _modItem = new ModbusRxTxCommand(Dev.ChannelId, Dev.Id,"普通报文",1);
            try
            {
                GetSendInfo();
            }
            catch (Exception e)
            {
                MsgLog(true, "初始化轮询命令出错:" + e.Message);
            }

            return true;
        }


        /// <summary>
        /// 根据数据项信息获取发送报文信息 功能码 寄存器起始地址 个数 
        /// </summary>
        /// <returns></returns>
        protected virtual bool GetSendInfo()
        {
            if (DataItems == null || DataItems.Count == 0)
            {
                return false;
            }
            _mSendFrame.Clear();  // 清空列表
            ModbusRxTxCommand mbPoll;
            ModbusTagObject tagObject;
            ModbusCode byFun;
            int startAddr, currAddr;
            int regCount = 0;
            int stepCnt, lastStep;
            int offset, index = 0;

            while (DataItems[index].Access == Access.只写)
            {
                index++;
                if (index == DataItems.Count)
                {
                    return false;
                }
            }
            tagObject = DataItems[index].TagObject as ModbusTagObject;
            byFun = tagObject.ReadFunCode;       // 功能码
            startAddr = DataItems[index].Address;  // 寄存器地址
            currAddr = startAddr;
            offset = index;
            //dataType = DataItems[0].DataType; // 数据类型
            stepCnt = DataItems[index].GetDataLength() / 2;
            lastStep = DataItems[index].GetDataLength() / 2;
            if (lastStep <= 0) // 类型为byte 时长度Datalen为1  在MakeSendFrame中判断是否Funcode为01 或02 如果不是则置为无效帧
            {
                lastStep = 1;
            }
            DataItem curItem;
            for (int i = index + 1; i < DataItems.Count; i++)
            {
                curItem = DataItems[i]; // 当前数据项
                tagObject = DataItems[i].TagObject as ModbusTagObject;
                stepCnt = curItem.GetDataLength() / 2;
                if (lastStep <= 0) // 类型为byte 时长度Datalen为1  在MakeSendFrame中判断是否Funcode为01 或02 如果不是则置为无效帧
                {
                    lastStep = 1;
                }
                currAddr += lastStep;
                if (tagObject == null) continue;
                if (currAddr == curItem.Address && byFun == tagObject.ReadFunCode && curItem.Access != Access.只写)
                {
                    regCount += lastStep;
                    lastStep = stepCnt;
                    currAddr = curItem.Address;
                }
                else
                {
                    mbPoll = new ModbusRxTxCommand(Dev.ChannelId, Dev.Id, "普通报文" + _mSendFrame.Count, 1);
                    mbPoll.DevAddr = (byte)Dev.Address;
                    mbPoll.FunCode = byFun;
                    mbPoll.RegAddr = (ushort)startAddr;

                    mbPoll.RegNum = (ushort)(regCount + lastStep);
                    lastStep = stepCnt;

                    mbPoll.StartIndex = offset; // 标记起始记录行号
                    mbPoll.DealReceiveMsg = DealReceiveMsg;
                    _mSendFrame.Add(mbPoll);
                    startAddr = curItem.Address;     // 寄存器地址
                    byFun = tagObject.ReadFunCode;      // 功能码
                    regCount = 0;
                    offset = i;
                    currAddr = startAddr;
                }
            }
            mbPoll = new ModbusRxTxCommand(Dev.ChannelId, Dev.Id, "普通报文" + _mSendFrame.Count, 1);
            mbPoll.DevAddr = (byte)Dev.Address;
            if (DataItems[offset].TagObject is ModbusTagObject modbusTagObject)
                mbPoll.FunCode = modbusTagObject.ReadFunCode;
            mbPoll.RegAddr = (ushort)startAddr;
            mbPoll.RegNum = (ushort)(regCount + stepCnt);
            mbPoll.StartIndex = offset;// 标记起始记录行号
            mbPoll.DealReceiveMsg = DealReceiveMsg;
            _mSendFrame.Add(mbPoll);
            if (_mSendFrame.Count <= 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        #endregion

        #region 轮询函数
        /// <summary>
        /// 轮询函数
        /// </summary>
        /// <returns></returns>
        public override bool RunPolling()
        {
            if (_mSendFrame == null || _mSendFrame.Count == 0) return false;
            _sendIndex++;
            if (_sendIndex < 0 || _sendIndex >= _mSendFrame.Count) _sendIndex = 0;

            _modItem = _mSendFrame[_sendIndex];
            if (ModbusHelper.MakeTcpSendFrame(_packageIndex++, ref _modItem))
            {
                this.Channel.PutCommand(_modItem);
            }
            else
            {
                return false;
            }
            return true;
        }
        #endregion

        #region 接收数据处理
        private void DealReceiveMsg(object sender, EventArgs e)
        {
            ModbusRxTxCommand rx = sender as ModbusRxTxCommand;
            if (rx == null || rx.ReceiveResult != MsgResult.RecOk) return;
            _modItem = rx;
            ExplainRxData(rx.ReceiveBytes);
        }
        /// <summary>
        /// 数据处理
        /// </summary>
        /// <param name="rxData"></param>
        /// <returns></returns>
        public  bool ExplainRxData(byte[] rxData)
        {
            if (_modItem.ReceiveResult != MsgResult.RecOk) return false;
            switch (_modItem.FunCode) // 写的功能码在检查接收报文时已处理
            {
                case ModbusCode.F01:
                    DealRxCoil(rxData, _modItem);
                    break;
                case ModbusCode.F02:
                    DealRxCoil(rxData, _modItem);
                    break;
                case ModbusCode.F03:
                    DealRxMultReg(rxData, _modItem);
                    break;
                case ModbusCode.F04:
                    DealRxMultReg(rxData, _modItem);
                    break;
            }
            return true;
        }

        /// <summary>
        /// 处理0x01 0x02 功能码接收数据
        /// </summary>
        /// <param name="pData"></param>
        /// <param name="modinfo"></param>
        /// <returns></returns>
        public bool DealRxCoil(byte[] pData, ModbusRxTxCommand modinfo)  // 检查接收包 
        {
            if (modinfo.FunCode != ModbusCode.F01 && modinfo.FunCode != ModbusCode.F02)
            {
                return true;
            }
            try
            {
                byte[] dataSrc = new byte[pData.Length - 9];
                Buffer.BlockCopy(pData, 3 + 6, dataSrc, 0, pData.Length - 9);

                int index = modinfo.StartIndex;
                UInt32 dataNum = modinfo.RegNum;
                DataItem temp;
                for (int i = 0; i < dataSrc.Length; i++)
                {
                    for (int j = 0; j < 8; j++)
                    {
                        if (dataNum <= i * 8 + j)
                        {
                            return true;
                        }
                        index = index + i * 8 + j;
                        temp = DataItems[index]; // 数据项
                        //lastValue = temp.CurValue;
                        if ((dataSrc[i] & (0x01 << j)) != 0)
                        {
                            temp.CurValue = 1;
                        }
                        else
                        {
                            temp.CurValue = 0;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return true;
        }
        /// <summary>
        /// 处理接收数据（03 04 功能码）
        /// </summary>
        /// <param name="pData">接收报文</param>
        /// <param name="modinfo">报文附加信息（插帧时使用）</param>
        /// <returns></returns>
        public bool DealRxMultReg(byte[] pData, ModbusRxTxCommand modinfo)  // 检查接收包 
        {
            if (modinfo.FunCode != ModbusCode.F03 && modinfo.FunCode != ModbusCode.F04)
            {
                return true;
            }
            byte[] dataSrc = new byte[pData.Length - 9];
            Buffer.BlockCopy(pData, 3 + 6, dataSrc, 0, pData.Length - 9);

            if (ExplainReceiveData(dataSrc, modinfo))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 解析接收报文
        /// </summary>
        /// <param name="dataSrc">原始字节数据</param>
        /// <param name="curPoll">轮询信息</param>
        /// <returns></returns>
        protected virtual bool ExplainReceiveData(byte[] dataSrc, ModbusRxTxCommand curPoll)
        {
            try
            {
                int offset = 0, index = curPoll.StartIndex;//index = pollInfo[RxTxCtrl.readIndex].startIndex
                double dMult, lastValue;
                DataType dataType;
                DataItem temp = DataItems[index];
                ModbusTagObject tagObject = temp.TagObject as ModbusTagObject;
                if (tagObject == null) return false;
                switch (Dev.ByteOrder)
                {
                    case ByteOrder.高位在前:         // 高位在前4321
                    case ByteOrder.高字在前:         // 高位在前4321
                        while (offset < dataSrc.Length && index < DataItems.Count)
                        {
                            temp = DataItems[index];
                            tagObject = temp.TagObject as ModbusTagObject;
                            if (tagObject == null) continue;
                            dataType = temp.DataType;
                            dMult = tagObject.Coefficient;


                            Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, temp.GetDataLength());
                            Array.Reverse(dataSrc, offset, temp.GetDataLength());
                            lastValue = temp.CurValue;
                            temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                            if (temp.PhyType == PhyType.信号量) // 遥信
                            {
                                DealSignal(temp, lastValue);
                            }

                            offset += temp.GetDataLength();
                            index++;
                        }
                        break;
                    case ByteOrder.低位在前:    // 低位在前1234
                        while (offset < dataSrc.Length && index < DataItems.Count)
                        {
                            temp = DataItems[index];
                            tagObject = temp.TagObject as ModbusTagObject;
                            if (tagObject == null) continue;
                            dataType = temp.DataType;
                            dMult = tagObject.Coefficient;

                            Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, temp.GetDataLength());
                            lastValue = temp.CurValue;
                            temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                            if (temp.PhyType == PhyType.信号量) // 遥信
                            {
                                DealSignal(temp, lastValue);
                            }
                            offset += temp.GetDataLength();
                            index++;
                        }
                        break;
                    case ByteOrder.低字在前:         // 低字在前2143
                        while (offset < dataSrc.Length && index < DataItems.Count)
                        {
                            temp = DataItems[index];
                            tagObject = temp.TagObject as ModbusTagObject;
                            if (tagObject == null) continue;
                            dataType = temp.DataType;
                            dMult = tagObject.Coefficient;
                            temp = DataItems[index];
                            if (temp.GetDataLength() == 2)
                            {
                                Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, 2);
                                Array.Reverse(dataSrc, offset, 2);
                                lastValue = temp.CurValue;
                                temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                                if (temp.PhyType == PhyType.信号量) // 遥信
                                {
                                    DealSignal(temp, lastValue);
                                }
                                offset += 2;
                            }
                            else if (temp.GetDataLength() == 4)
                            {
                                Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, 4);
                                for (int i = 0; i < 2; i++)
                                {
                                    Array.Reverse(dataSrc, offset + 2 * i, 2);
                                }
                                lastValue = temp.CurValue;
                                temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                                if (temp.PhyType == PhyType.信号量) // 遥信
                                {
                                    DealSignal(temp, lastValue);
                                }
                                offset += 4;
                            }
                            else
                            {
                                Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, temp.GetDataLength());
                                lastValue = temp.CurValue;
                                temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                                if (temp.PhyType == PhyType.信号量) // 遥信
                                {
                                    DealSignal(temp, lastValue);
                                }
                                offset += temp.GetDataLength();
                            }
                            index++;
                        }
                        break;
                    case ByteOrder.三四一二:         // 3412
                        while (offset < dataSrc.Length && index < DataItems.Count)
                        {
                            temp = DataItems[index];
                            tagObject = temp.TagObject as ModbusTagObject;
                            if (tagObject == null) continue;
                            dataType = temp.DataType;
                            dMult = tagObject.Coefficient;
                            temp = DataItems[index];
                            if (temp.GetDataLength() == 2)
                            {
                                Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, 2);
                                lastValue = temp.CurValue;
                                temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                                if (temp.PhyType == PhyType.信号量) // 遥信
                                {
                                    DealSignal(temp, lastValue);
                                }
                                offset += 2;

                            }
                            else if (temp.GetDataLength() == 4)
                            {
                                Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, 4);
                                for (int i = 0; i < 2; i++)
                                {
                                    Array.Reverse(dataSrc, offset + 2 * i, 2);
                                }
                                Array.Reverse(dataSrc, offset, 4);
                                lastValue = temp.CurValue;
                                temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                                if (temp.PhyType == PhyType.信号量) // 遥信
                                {
                                    DealSignal(temp, lastValue);
                                }
                                offset += 4;
                            }
                            else
                            {
                                Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, temp.GetDataLength());
                                lastValue = temp.CurValue;
                                temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                                if (temp.PhyType == PhyType.信号量) // 遥信
                                {
                                    DealSignal(temp, lastValue);
                                }
                                offset += temp.GetDataLength();
                            }
                            index++;
                        }
                        break;
                    default: // "4321"
                        while (offset < dataSrc.Length && index < DataItems.Count)
                        {
                            temp = DataItems[index];
                            tagObject = temp.TagObject as ModbusTagObject;
                            if (tagObject == null) continue;
                            dataType = temp.DataType;
                            dMult = tagObject.Coefficient;
                            temp = DataItems[index];

                            Buffer.BlockCopy(dataSrc, offset, tagObject.RecBytes, 0, temp.GetDataLength());
                            Array.Reverse(dataSrc, offset, temp.GetDataLength());
                            lastValue = temp.CurValue;
                            temp.CurValue = ExplainData(dataType, dataSrc, offset, dMult, tagObject.PointNum);
                            if (temp.PhyType == PhyType.信号量) // 遥信
                            {

                                DealSignal(temp, lastValue);
                            }
                            offset += temp.GetDataLength();
                            index++;
                        }
                        break;
                }
                return true;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// 解析接收报文为实际值
        /// </summary>
        /// <param name="dataType">数据类型</param>
        /// <param name="dataSrc">报文字节</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="multiple">放大倍数</param>
        /// <param name="pointNum">小数点个数</param>
        /// <returns></returns>
        private double ExplainData(DataType dataType, byte[] dataSrc, int startIndex, double multiple, int pointNum)
        {
            double tempVal = 0;
            if (multiple < 1)
            {
                multiple = Math.Round(multiple, pointNum);  // 由于Multiple为浮点型，不能准确表示数值，
            }                                               // 当被乘数较大时，会产生不少误差，故要四舍五入 
            switch (dataType)
            {
                case DataType.Int16: // 短整形
                    try
                    {
                        tempVal = BitConverter.ToInt16(dataSrc, startIndex) * multiple;
                    }
                    catch
                    { }
                    break;
                case DataType.Int32: // 整形
                    try
                    {
                        tempVal = BitConverter.ToInt32(dataSrc, startIndex) * multiple;
                    }
                    catch
                    { }
                    break;
                case DataType.UInt16: // 短整形
                    try
                    {
                        tempVal = BitConverter.ToUInt16(dataSrc, startIndex) * multiple;
                    }
                    catch
                    { }
                    break;
                case DataType.UInt32: // 整形
                    try
                    {
                        tempVal = BitConverter.ToUInt32(dataSrc, startIndex) * multiple;
                    }
                    catch
                    { }
                    break;
                case DataType.Single: // 浮点型
                    try
                    {
                        tempVal = BitConverter.ToSingle(dataSrc, startIndex) * multiple;
                    }
                    catch
                    { }
                    break;
                case DataType.Double:
                    try
                    {
                        tempVal = BitConverter.ToDouble(dataSrc, startIndex) * multiple;
                    }
                    catch
                    { }
                    break;
                case DataType.BCD4:
                    try
                    {
                        StringBuilder strB = new StringBuilder();
                        for (int i = startIndex; i < startIndex + 4; i++)
                        {
                            strB.Append(dataSrc[i].ToString("X2"));
                        }
                        int TempVal = int.Parse(strB.ToString());
                        tempVal = TempVal * multiple;
                    }
                    catch
                    { }
                    break;
                case DataType.BCD2:
                    try
                    {
                        StringBuilder strB = new StringBuilder();
                        for (int i = startIndex; i < startIndex + 2; i++)
                        {
                            strB.Append(dataSrc[i].ToString("X2"));
                        }
                        int TempVal = int.Parse(strB.ToString());
                        tempVal = TempVal * multiple;
                    }
                    catch
                    { }
                    break;
                default:
                    try
                    {
                        tempVal = BitConverter.ToUInt16(dataSrc, startIndex) * multiple;
                    }
                    catch
                    { }
                    break;
            }
            string strPoint = tempVal.ToString(CultureInfo.InvariantCulture);
            if (strPoint.Contains("."))
            {
                int pointLength = strPoint.Length - strPoint.IndexOf(".", StringComparison.Ordinal) - 1;
                if (pointLength > pointNum)
                {
                    if (pointNum == 0) pointNum = 3;
                    tempVal = Math.Round(tempVal, pointNum);
                }
            }
            return tempVal;
        }


        #endregion

        #region 命令提交

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="operid">命令Id</param>
        /// <returns></returns>
        public override RxTxCommand PostToExcute(string operid)
        {
            if (Operations.ContainsKey(operid))
            {
                Operation oper = DealOperationWithPara(Operations[operid], null); // 处理地址
                RxTxCommand cmd = new RxTxCommand(Dev.ChannelId, Dev.Id, oper.Name);
                cmd.IsAscii = oper.IsAscii;
                cmd.SendBytes = oper.MsgBuffer;
                cmd.NeedReply = oper.NeedReply;
                cmd.Timeout = oper.Timeout;
                cmd.DealReceiveMsg += Cmd_DealReceiveMsg;
                return cmd;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 带参数执行命令
        /// </summary>
        /// <param name="operid">命令Id</param>
        /// <param name="paras">参数集合</param>
        /// <returns></returns>
        public override RxTxCommand PostToExcute(string operid, string[] paras)
        {
            if (Operations.ContainsKey(operid))
            {
                Operation oper = DealOperationWithPara(Operations[operid], paras);
                RxTxCommand cmd = new RxTxCommand(Dev.ChannelId, Dev.Id, oper.Name);
                cmd.IsAscii = oper.IsAscii;
                cmd.NeedReply = oper.NeedReply;
                cmd.Timeout = oper.Timeout;
                cmd.SendBytes = oper.MsgBuffer;
                cmd.DealReceiveMsg += Cmd_DealReceiveMsg;
                return cmd;
            }
            else
            {
                return null;
            }
        }

        private void Cmd_DealReceiveMsg(object sender, EventArgs e)
        {
            RxTxCommand cmd = sender as RxTxCommand;
            if (cmd != null)
            {
                Console.WriteLine("接收:" + cmd.ReceiveMsg);
            }
        }

        #endregion

        #region 数据项额外参数处理

        public override List<DataItem> DeSerializeDataItems(List<DataItem> items)
        {
            items = DeSerialize<ModbusTagObject>(items);
            return items;
        }
        public override DataItem DeSerializeDataItem(DataItem item)
        {
            item = DeSerialize<ModbusTagObject>(item);
            return item;
        }
        public override DataItem DecorateItem(DataItem item)
        {
            item.TagObject = new ModbusTagObject();
            return item;
        }

        #endregion

        #region 数值修改

        public override RxTxCommand WriteValue(string dataId, double value)
        {
            DataItem dataItem = DataItems.First(sss => sss.Id == dataId);
            if (dataItem == null || dataItem.Access == Access.只读)
            {
                return null;
            }
            ModbusTagObject tagObject = dataItem.TagObject as ModbusTagObject;
            if (tagObject == null) return null;
            ModbusRxTxCommand modIten = new ModbusRxTxCommand(Dev.ChannelId, Dev.Id, "插帧报文", 1);
            modIten.DevAddr = (byte)Dev.Address;
            modIten.FunCode = tagObject.WriteFunCode;
            modIten.RegAddr = (ushort)dataItem.Address;
            modIten.RegNum = (ushort)dataItem.GetDataLength();
            modIten.NeedReply = true;
            if (modIten.FunCode == ModbusCode.F05)
            {
                List<byte> bytes = new List<byte>();
                bytes.AddRange(BitConverter.GetBytes((UInt16)value));
                bytes.Reverse();
                modIten.WriteData = bytes.ToArray();
            }
            else
            {
                modIten.WriteData = GetBytesFromData(value, tagObject.Coefficient, dataItem.DataType, Dev.ByteOrder);
            }
            modIten.DealReceiveMsg = DealReceiveMsg;

            ModbusHelper.MakeSendFrame(ref modIten);


            Channel.PutInsertCommand(modIten);// 放入插帧

            if (dataItem.Access == Access.读写) // 回读数据
            {
                ModbusRxTxCommand readModIten = new ModbusRxTxCommand(Dev.ChannelId, Dev.Id, "插帧报文", 1);
                readModIten.StartIndex = dataItem.Position;
                readModIten.DevAddr = (byte)Dev.Address;
                readModIten.FunCode = tagObject.ReadFunCode;
                readModIten.RegAddr = (ushort)dataItem.Address;
                readModIten.RegNum = (ushort)dataItem.GetDataLength();
                if (readModIten.RegNum == 0)
                {
                    readModIten.RegNum = 1;
                }
                readModIten.DealReceiveMsg = DealReceiveMsg;
                ModbusHelper.MakeSendFrame(ref readModIten);


                Channel.PutInsertCommand(readModIten);// 放入插帧
            }
            return modIten;
        }

        public override RxTxCommand WriteValue(string startId, byte[] buffer)
        {
            DataItem dataItem = DataItems.First(sss => sss.Id == startId);
            if (dataItem == null || dataItem.Access == Access.只读)
            {
                return null;
            }
            ModbusTagObject tagObject = dataItem.TagObject as ModbusTagObject;
            if (tagObject == null) return null;
            ModbusRxTxCommand modIten = new ModbusRxTxCommand(Dev.ChannelId, Dev.Id, "插帧报文", 1);
            modIten.DevAddr = (byte)Dev.Address;
            modIten.FunCode = tagObject.WriteFunCode;
            modIten.RegAddr = (ushort)dataItem.Address;
            modIten.RegNum = (ushort)(buffer.Length / 2);
            modIten.NeedReply = true;
            if (modIten.FunCode == ModbusCode.F05)
            {
                List<byte> bytes = new List<byte>();
                bytes.AddRange(buffer);
                bytes.Reverse();
                modIten.WriteData = bytes.ToArray();
            }
            else
            {
                modIten.WriteData = buffer;
            }
            modIten.DealReceiveMsg = DealReceiveMsg;

            ModbusHelper.MakeSendFrame(ref modIten);


            Channel.PutInsertCommand(modIten);// 放入插帧

            if (dataItem.Access == Access.读写) // 回读数据
            {
                ModbusRxTxCommand readModIten = new ModbusRxTxCommand(Dev.ChannelId, Dev.Id, "插帧报文", 1);
                readModIten.StartIndex = dataItem.Position;
                readModIten.DevAddr = (byte)Dev.Address;
                readModIten.FunCode = tagObject.ReadFunCode;
                readModIten.RegAddr = (ushort)dataItem.Address;
                readModIten.RegNum = (ushort)(buffer.Length / 2);
                if (readModIten.RegNum == 0)
                {
                    readModIten.RegNum = 1;
                }
                readModIten.DealReceiveMsg = DealReceiveMsg;
                ModbusHelper.MakeSendFrame(ref readModIten);


                Channel.PutInsertCommand(readModIten);// 放入插帧
            }
            return modIten;
        }

        public byte[] GetBytesFromData(double dData, double dmult, DataType dataType, ByteOrder byteSqueue)
        {
            byte[] byData;

            try
            {
                switch (dataType)
                {
                    case DataType.Int16:
                        byData = BitConverter.GetBytes(Convert.ToInt16((dData / dmult)));
                        break;
                    case DataType.Int32:
                        byData = BitConverter.GetBytes(Convert.ToInt32((dData / dmult)));
                        break;
                    case DataType.Single:
                        byData = BitConverter.GetBytes(Convert.ToSingle((dData / dmult)));
                        break;
                    case DataType.UInt16:
                        byData = BitConverter.GetBytes(Convert.ToUInt16((dData / dmult)));
                        break;
                    case DataType.UInt32:
                        byData = BitConverter.GetBytes(Convert.ToUInt32((dData / dmult)));
                        break;
                    case DataType.Int64:
                        byData = BitConverter.GetBytes(Convert.ToInt64((dData / dmult)));
                        break;
                    case DataType.Double:
                        byData = BitConverter.GetBytes(dData / dmult);
                        break;
                    case DataType.Byte:
                        byData = BitConverter.GetBytes(Convert.ToByte((dData / dmult)));
                        break;
                    case DataType.BCD4:
                        byData = BitConverter.GetBytes(Convert.ToUInt32((dData / dmult).ToString(CultureInfo.InvariantCulture), 16));
                        break;
                    case DataType.BCD2:
                        byData = BitConverter.GetBytes(Convert.ToUInt16((dData / dmult).ToString(CultureInfo.InvariantCulture), 16));
                        break;
                    default:
                        return null;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message);
                return null;
            }
            switch (byteSqueue)
            {
                case ByteOrder.高位在前:         // 高位在前4321
                case ByteOrder.高字在前:         // 高字在前4321
                    Array.Reverse(byData, 0, byData.Length);
                    break;
                case ByteOrder.低位在前:         // 低位在前1234
                    break;
                case ByteOrder.低字在前:         // 低字在前2143
                    for (int i = 0; i < byData.Length / 2; i++)
                    {
                        Array.Reverse(byData, 2 * i, 2);
                    }
                    break;
                case ByteOrder.三四一二:         // 3412
                    if (byData.Length > 2)
                    {
                        for (int i = 0; i < byData.Length / 2; i++)
                        {
                            Array.Reverse(byData, 2 * i, 2);
                        }
                        for (int i = 0; i < byData.Length / 4; i++)
                        {
                            Array.Reverse(byData, 4 * i, 4);
                        }
                    }
                    break;
                default:
                    for (int i = 0; i < byData.Length / 4; i++)
                    {
                        byData[i] = 0;
                    }
                    break;
            }
            return byData;
        }

        #endregion
    }
}
